package livingarea;

import livingarea.other.Statistics;
import livingarea.other.Coordinates;
import livingarea.Members.Predator;
import livingarea.Members.Pray;
import livingarea.Members.AreaMember;
import java.util.ArrayList;
import java.util.List;
import livingarea.Members.Factory.AreaMemberFactory;
import livingarea.Members.Factory.GreeneryFactory;
import livingarea.Members.Factory.PrayFactory;
import livingarea.Members.Factory.PredatorFactory;
import livingarea.Members.Greenery;
import livingarea.Members.Position;

/**
 * This class describe the entity of Living area that consist of defined
 * quantity of squire parts, with some number of different kind`s of beasts.
 *
 * @author Muzalevskiy Vitaliy
 */
public class LivingArea {

    public static final int DEFAULT_ITERATION_COUNT = 200;
    public static final int DEFAULT_PRAY_COUNT = 50;
    public static final int DEFAULT_PREDATOR_COUNT = 50;
    public static final int DEFAULT_GREENERY_COUNT = 5;
    private Coordinates coordinates;
    /**
     * <code> AreaObjects </code> of areaMembers in living area.
     */
    private List<AreaMember> areaMembersList;
    private Statistics statistics;
    /**
     * Intermediate
     * <code> List </code> of areaMembers that ware born in current iteration.
     */
    private List<AreaMember> addList;
    /**
     * Intermediate
     * <code> List </code> of areaMembers that died in current iteration.
     */
    private List<AreaMember> removeList;
    private List<Position> blockedPositions;

    public LivingArea() {
        coordinates = new Coordinates();
        areaMembersList = new ArrayList<>();
        addList = new ArrayList<>();
        removeList = new ArrayList<>();
        blockedPositions = new ArrayList<>();
        statistics = new Statistics();
    }

    /**
     * Add new areaMember to intermediate list until the end of current
     * iteration.
     *
     * @param areaMember - new fish that need to be added to swimming pool.
     */
    public void addMember(AreaMember areaMember) {
        addList.add(areaMember);
    }

    /**
     * Add died areaMember to intermediate list until the end of current
     * iteration.
     *
     * @param areaMember - fish that need to be removed from swimming pool.
     */
    public void removeMember(AreaMember areaMember) {
        removeList.add(areaMember);
    }
    
    public void blockPosition(Position position){
        blockedPositions.add(position);
    }
    
    public boolean positionIsBlocked(Position position){
        return blockedPositions.contains(position);
    }

    /**
     * This method used to include values from
     * <code> addList </code> and remove values at
     * <code> removeList </code> from
     * <code> areaMembersList </code>.
     */
    private void rewriteAreaMembersList() {
        areaMembersList.addAll(addList);
        areaMembersList.removeAll(removeList);
        addList.clear();
        removeList.clear();
    }

    public int getAreaMembersCount() {
        return areaMembersList.size();
    }

    public AreaMember getAreaMember(int numberInList) {
        return areaMembersList.get(numberInList);
    }
    
    public boolean isMemberExist(AreaMember member){
        return areaMembersList.contains(member);
    }

    /**
     * Start modeling of process.
     *
     * @param itearationCount quantity of iterations that current method make.
     */
    public void start(int itearationCount) {
        for (int i = 0; i < itearationCount; i++) {
            for (AreaMember areaMember : areaMembersList) {
                areaMember.lifeCicle();
            }
            rewriteAreaMembersList();
        }
    }

    /**
     * Start modeling with all default values.
     */
    public void start() {
        for (int i = 0; i < DEFAULT_PRAY_COUNT; i++) {
            AreaMemberFactory prayFactory = new PrayFactory();
            prayFactory.create(this);
            statistics.increasePrayCount();
        }
        for (int i = 0; i < DEFAULT_PREDATOR_COUNT; i++) {
            AreaMemberFactory predatorFactory = new PredatorFactory();
            predatorFactory.create(this);
            statistics.increasePredatorCount();
        }
        for (int i = 0; i < DEFAULT_GREENERY_COUNT; i++) {
            AreaMemberFactory greeneryFactory = new GreeneryFactory();
            greeneryFactory.create(this);
            statistics.increaseGreeneryCount();
        }
        start(DEFAULT_ITERATION_COUNT);
    }

    public Statistics getStatistics() {
        return statistics;
    }

    /**
     * @return the coordinates
     */
    public Coordinates getCoordinates() {
        return coordinates;
    }

    public boolean memberIsDead(AreaMember member) {
        return removeList.contains(member);
    }
}
